package top.jiangqiang.qyblog.common.id;

import cn.hutool.core.collection.ConcurrentHashSet;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;

import java.math.BigInteger;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;

/**
 * id=时间戳+固定位数的数字
 * 每一个时间戳对应多个id
 * <p>
 * 由于ts的数字最大只能接受9007199254740991，超过后长度的位会变成0
 *
 * @author JiangQiang
 */
public final class DefaultIDGenerator implements IDGenerator {
    //每一毫秒最多可生成的id数量，会占用(10/10)个长度
    private static final int COUNT = 10;
    //末尾拼接的随机数长度
    private static final int RANDOM_LENGTH = 1;
    private static volatile IDGenerator instance;
    //记录已经拿到的最大id
    private final AtomicLong maxId = new AtomicLong(0);
    private final Consumer<Long> consumer;

    private DefaultIDGenerator(Long currentMaxId, Consumer<Long> callback) {
        this.maxId.set(currentMaxId != null ? currentMaxId : 0);
        this.consumer = callback;
    }

    /**
     * @return 字母，数字组成的字符串
     */
    @Override
    public String nextUUID() {
        return new BigInteger(String.valueOf(nextId()), 10).toString(36);
    }

    @Override
    public Long nextId() {
        return this.maxId.updateAndGet(lastId -> {
            synchronized (DefaultIDGenerator.class) {
                //每一个时间戳都有多个id 这里计算出当前时间戳对应的第一个id
                long timestampSequence = Long.parseLong(System.currentTimeMillis() * COUNT + 1 + RandomUtil.randomNumbers(RANDOM_LENGTH));
                long currentId;
                if (lastId < timestampSequence) {
                    currentId = timestampSequence;
                } else {
                    //除以1000就是去除三位随机数，然后自增，再拼接三位随机数
                    currentId = Long.parseLong((lastId / ((int) Math.pow(10, RANDOM_LENGTH))) + 1 + RandomUtil.randomNumbers(RANDOM_LENGTH));
                }
                if (consumer != null) {
                    consumer.accept(currentId);
                }
                return currentId;
            }
        });
    }

    public static IDGenerator getInstance() {
        return getInstance(null, null);
    }

    public static IDGenerator getInstance(Long currentMaxId) {
        return getInstance(currentMaxId, null);
    }

    public static IDGenerator getInstance(Consumer<Long> callback) {
        return getInstance(null, callback);
    }

    /**
     * 创建标识符全局唯一的id生成器，
     *
     * @param currentMaxId 传入当前已经生成过的最大的id
     * @return
     */
    public static IDGenerator getInstance(Long currentMaxId, Consumer<Long> callback) {
        if (instance == null) {
            synchronized (IDGenerator.class) {
                if (instance == null) {
                    instance = new DefaultIDGenerator(currentMaxId, callback);
                }
            }
        }
        return instance;
    }

    public static void main(String[] args) {
        ConcurrentHashSet<Long> hashSet = new ConcurrentHashSet<Long>(new HashSet<>());
        IDGenerator instance1 = getInstance();
        for (int i = 0; i < 100; i++) {
            for (int j = 0; j < 100; j++) {
                new Thread(()->{
                    Long aLong = instance1.nextId();
                    hashSet.add(aLong);
                    System.out.println(aLong);
                }).start();
            }
        }
        ThreadUtil.sleep(1000);
        System.out.println(hashSet.size());
    }
}
